package com.huilian.iotbox.data.service.impl;

import com.alibaba.fastjson.JSON;
import com.huilian.iotbox.data.common.RedisKey;
import com.huilian.iotbox.data.common.RedisLockKey;
import com.huilian.iotbox.data.dao.AppletOrOfficialAccountCommonDao;
import com.huilian.iotbox.data.dto.MemberStoreBalanceDto;
import com.huilian.iotbox.data.dto.MerchantStoreDto;
import com.huilian.iotbox.data.enums.AppletOrOfficialAccountPlatformTypeEnum;
import com.huilian.iotbox.data.po.AppletOrOfficialAccount;
import com.huilian.iotbox.data.po.Member;
import com.huilian.iotbox.data.service.AppletOrOfficialAccountCommonService;
import com.huilian.iotbox.data.service.ErrorLogCommonService;
import com.huilian.iotbox.data.service.MemberStoreBalanceCommonService;
import com.huilian.iotbox.data.service.MerchantStoreCommonService;
import com.huilian.iotbox.data.vo.MemberStoreBalanceVo;
import com.huilian.iotbox.data.vo.MerchantStoreVo;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.io.Serializable;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Slf4j
@Service
public class AppletOrOfficialAccountCommonServiceImpl implements AppletOrOfficialAccountCommonService {

    @Autowired
    private RedissonClient redissonClient;
    @Autowired
    private ErrorLogCommonService errorLogCommonService;
    @Autowired
    private MerchantStoreCommonService merchantStoreCommonService;
    @Autowired
    private RedisTemplate<String, Serializable> redisCacheTemplate;
    @Autowired
    private MemberStoreBalanceCommonService memberStoreBalanceCommonService;
    @Autowired
    private AppletOrOfficialAccountCommonDao appletOrOfficialAccountCommonDao;

    @Override
    public AppletOrOfficialAccount findOneById(int id) {
        return appletOrOfficialAccountCommonDao.findOneById(id);
    }

    @Override
    public AppletOrOfficialAccount findOneByWeChatAppId(String appId) {
        final String weChatAppIdLockKey = String.format(RedisLockKey.DEDICATED_WECHAT_APPLET_APPID, appId);
        RLock lock = redissonClient.getLock(weChatAppIdLockKey);
        AppletOrOfficialAccount appletOrOfficialAccount = null;
        try {
            final boolean tryLock = lock.tryLock(10, TimeUnit.SECONDS);
            if (tryLock) {
                final String appletOrOfficialAccountKey = String.format(RedisKey.APPLET_OR_OFFICIAL_ACCOUNT, appId);
                appletOrOfficialAccount = (AppletOrOfficialAccount) redisCacheTemplate.opsForValue().get(appletOrOfficialAccountKey);
                if (StringUtils.isEmpty(appletOrOfficialAccount)) {
                    appletOrOfficialAccount = appletOrOfficialAccountCommonDao.findOneByWeChatAppId(appId);
                    redisCacheTemplate.opsForValue().set(appletOrOfficialAccountKey, appletOrOfficialAccount, 1, TimeUnit.HOURS);
                }
            } else {
                log.warn("weChatAppIdLockKey-未获取到锁");
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (!StringUtils.isEmpty(lock) && lock.isHeldByCurrentThread()) {
                lock.unlock();
                log.info("weChatAppIdLockKey-解锁成功");
            } else {
                log.error("weChatAppIdLockKey-lock is null or lock isNotHeldByCurrentThread");
            }
            return appletOrOfficialAccount;
        }
    }

    @Override
    public AppletOrOfficialAccount findOneByALiAppId(String appId) {
        final String aLiAppIdLockKey = String.format(RedisLockKey.DEDICATED_ALI_APPLET_APPID, appId);
        RLock lock = redissonClient.getLock(aLiAppIdLockKey);
        AppletOrOfficialAccount appletOrOfficialAccount = null;
        try {
            final boolean tryLock = lock.tryLock(10, TimeUnit.SECONDS);
            if (tryLock) {
                final String appletOrOfficialAccountKey = String.format(RedisKey.APPLET_OR_OFFICIAL_ACCOUNT, appId);
                appletOrOfficialAccount = (AppletOrOfficialAccount) redisCacheTemplate.opsForValue().get(appletOrOfficialAccountKey);
                if (StringUtils.isEmpty(appletOrOfficialAccount)) {
                    appletOrOfficialAccount = appletOrOfficialAccountCommonDao.findOneByALiAppId(appId);
                    redisCacheTemplate.opsForValue().set(appletOrOfficialAccountKey, appletOrOfficialAccount, 1, TimeUnit.HOURS);
                }
            } else {
                log.warn("aLiAppIdLockKey-未获取到锁");
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (!StringUtils.isEmpty(lock) && lock.isHeldByCurrentThread()) {
                lock.unlock();
                log.info("aLiAppIdLockKey-解锁成功");
            } else {
                log.error("aLiAppIdLockKey-lock is null or lock isNotHeldByCurrentThread");
            }
            return appletOrOfficialAccount;
        }
    }

    /**
     * 专属小程序自动插入member_store_balance记录
     *
     * @param appletOrOfficialAccount
     * @param memberInfo
     */
    @Override
    public void dedicatedExistConsume(AppletOrOfficialAccount appletOrOfficialAccount, Member memberInfo) {
        try {
            if (AppletOrOfficialAccountPlatformTypeEnum.MERCHANT.getCode().equals(appletOrOfficialAccount.getPlatformType())) {
                MerchantStoreDto merchantStoreDto = new MerchantStoreDto();
                merchantStoreDto.setDedicatedWeChatApplet(appletOrOfficialAccount.getId());
                List<MerchantStoreVo> merchantStoreVos = merchantStoreCommonService.findAllMerchantStoreByCondition(merchantStoreDto);
                if (!StringUtils.isEmpty(merchantStoreVos) && merchantStoreVos.size() > 0) {
                    for (MerchantStoreVo merchantStoreVo : merchantStoreVos) {
                        MemberStoreBalanceDto memberStoreBalanceDto = new MemberStoreBalanceDto();
                        memberStoreBalanceDto.setMemberId(memberInfo.getId());
                        memberStoreBalanceDto.setMerchantStoreId(merchantStoreVo.getId());
                        final MemberStoreBalanceVo memberStoreBalanceVo = memberStoreBalanceCommonService.findMemberStoreBalanceByMerchantStoreId(memberStoreBalanceDto);

                        if (StringUtils.isEmpty(memberStoreBalanceVo)) {
                            memberStoreBalanceCommonService.add(memberInfo.getId(), merchantStoreVo.getId(), merchantStoreVo.getUserId(), null);
                        }
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            errorLogCommonService.writerInfoException("专属小程序自动插入member_store_balance记录异常", null, e);
            log.error("memberInfo:" + JSON.toJSONString(memberInfo));
            log.error("appletOrOfficialAccount:" + JSON.toJSONString(appletOrOfficialAccount));
        }
    }
}
